package io.persimmon.core.module.log;

import io.persimmon.core.module.call.Callback;
import io.persimmon.core.module.call.Consumer;
import io.persimmon.core.module.call.Runback;
import lombok.Getter;

@Getter
public class CostLog<T> {

    private Callback<T> callback;
    private boolean executed = false;
    private CostLogResult<T> costLogResult;

    public static <T> CostLog<T> create(Runback runback) {
        CostLog<T> costLog = new CostLog<>();
        costLog.callback = () -> {
            runback.run();
            return null;
        };
        return costLog;
    }

    public static <T> CostLog<T> create(Callback<T> callback) {
        CostLog<T> costLog = new CostLog<>();
        costLog.callback = callback;
        return costLog;
    }

    public CostLog<T> preExecute(Runback runback) {
        runback.run();
        return this;
    }

    public CostLog<T> execute() {
        executed();
        return this;
    }

    public CostLog<T> postExecute(Consumer<CostLogResult<T>> consumer) {
        executed();
        consumer.accept(this.costLogResult);
        return this;
    }

    public T getResult() {
        executed();
        return costLogResult.getResult();
    }

    private void executed() {
        if (executed) {
            return;
        }
        long start = System.currentTimeMillis();
        T call = callback.call();
        long cost = System.currentTimeMillis() - start;
        this.costLogResult = new CostLogResult<>(call, cost);
        this.executed = true;
    }
}
